/** @file    FormScreenshoter.cpp
 *  @author  Alessandro Polo
 *  @version $Id: FormScreenshoter.cpp 2197 2010-03-23 09:35:09Z alex $
 *  @brief
 * File containing methods for the wosh::gui::FormScreenshoter class.
 * The header for this class can be found in FormScreenshoter.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include "FormScreenshoter.h"
 #include "ui_FormScreenshoter.h"
 #include <QtGui>
 #include "WoshShopWindow.h"


using namespace std;
namespace wosh {
 namespace application {

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

FormScreenshoter::FormScreenshoter(QWidget *parent) : QWidget(parent, Qt::WindowStaysOnTopHint)
 {
	this->m_ui = new Ui::FormScreenshoter();
	this->m_ui->setupUi(this);

	this->grabKeyboard();//bug

	connect(this->m_ui->btnTakeShot, SIGNAL(clicked()), this, SLOT(btnTakeShot_clicked()) ),
	connect(this->m_ui->btnSaveTo, SIGNAL(clicked()), this, SLOT(btnSaveTo_clicked()) ),
	connect(this->m_ui->btnSave, SIGNAL(clicked()), this, SLOT(btnSave_clicked()) ),
	connect(this->m_ui->radioTargetDesktop, SIGNAL(clicked()), this, SLOT(btnTakeShot_clicked()) ),
	connect(this->m_ui->radioTargetWoshshop, SIGNAL(clicked()), this, SLOT(btnTakeShot_clicked()) ),
	connect(this->m_ui->radioTargetWidgetActive, SIGNAL(clicked()), this, SLOT(btnTakeShot_clicked()) ),

	this->quickSaveLastPath = QDir("../var/extras/screenshots").absolutePath() + "/";
	this->m_ui->txtOutputFolder->setText( this->quickSaveLastPath );
 }

FormScreenshoter::~FormScreenshoter() {
	delete this->m_ui;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormScreenshoter::changeEvent(QEvent* e) {
	QWidget::changeEvent(e);
	if ( e->type() == QEvent::LanguageChange )
		this->m_ui->retranslateUi(this);
 }

void FormScreenshoter::resizeEvent(QResizeEvent* e) {
QWidget::resizeEvent(e);
	QSize scaledSize = this->originalPixmap.size();
	scaledSize.scale(this->m_ui->lblPreview->size(), Qt::KeepAspectRatio);
	if ( !this->m_ui->lblPreview->pixmap() || scaledSize != this->m_ui->lblPreview->pixmap()->size() )
		updatePreview();
 }

void FormScreenshoter::keyPressEvent(QKeyEvent* e) {
	if ( this->m_ui->radioTargetWidget->isChecked() && e->key() == Qt::Key_Print ) {
		QPoint mousePos = QCursor::pos();
		QWidget* widgetTopWindow = qApp->widgetAt( mousePos ); // widgetAt  
		if ( widgetTopWindow == NULL ) {
			QMessageBox::critical(this, tr("ScreenShot Warning"), tr("No window found!") );
		 }
		else {
			QWidget* widget = widgetTopWindow->childAt( mousePos );
			if ( widgetTopWindow == NULL ) {
				QMessageBox::critical(this, tr("ScreenShot Warning"), tr("No widget found!") );
			 }
			else {
				QString name = widget->objectName();
				IReflection* irWin = dynamic_cast<IReflection*>(widget);
				if ( irWin != NULL )
					name = QString( irWin->getClassName() );
				this->selectedWidgetId = widget->winId();
				this->m_ui->lblScreenShotDescription->setText(tr("Selected Widget %1 [%2]").arg(name).arg((qint64)this->selectedWidgetId));
				this->m_ui->txtFileName->setText("WOSH.GUI." + name + ".%1.");
				return;
			 }
		 }
	 }
	QWidget::keyPressEvent(e);
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormScreenshoter::updatePreview() {
	this->m_ui->lblPreview->setPixmap(this->originalPixmap.scaled(this->m_ui->lblPreview->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
 }


QString FormScreenshoter::getCurrentFileName() const {
	return QString(this->m_ui->txtFileName->text()).arg(0);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormScreenshoter::shootScreen() {
	if ( this->m_ui->chkAutoHideMe->isChecked() )
		hide();
	if ( this->m_ui->spinShotDelay->value() != 0 ) qApp->beep();
	this->originalPixmap = QPixmap(); // clear image for low memory situations on embedded devices.

	if ( this->m_ui->radioTargetDesktop->isChecked() ) {
		this->originalPixmap = QPixmap::grabWindow(QApplication::desktop()->winId());
		this->m_ui->lblScreenShotDescription->setText(tr("Screenshot of User Desktop"));
		this->m_ui->txtFileName->setText("Desktop.%1.");
	 }
	else if ( this->m_ui->radioTargetWoshshop->isChecked() ) {
		this->originalPixmap = QPixmap::grabWindow( WoshShopWindow::getInstance()->winId() );
		this->m_ui->lblScreenShotDescription->setText(tr("Screenshot of WOSH WorkShop application"));
		this->m_ui->txtFileName->setText("WOSH.WorkShop.%1.");
	}
	else if ( this->m_ui->radioTargetWidget->isChecked() ) {
		if ( this->selectedWidgetId == 0 ) {
			QMessageBox::warning(this, tr("ScreenShot Warning"), tr("Failed selecting widget. Widget ID is invalid!") );
		 }
		this->m_ui->lblScreenShotDescription->setText(tr("Screenshot of Selected Widget [%1]").arg((qint64)this->selectedWidgetId));
		this->m_ui->txtFileName->setText("WOSH.GUI.%2.%1.");
	 }
	else if ( this->m_ui->radioTargetWidgetActive->isChecked() ) {
		QMdiArea* mdiArea = WoshShopWindow::getInstance()->getDocumentArea();
		QMdiSubWindow * mdiWindow = mdiArea->activeSubWindow();
		if ( mdiWindow == NULL )
			mdiWindow = mdiArea->currentSubWindow();
		if ( mdiWindow == NULL ) {
			QMessageBox::critical(this, tr("ScreenShot Warning"), tr("No active widget found!") );
		 }
		else {
			this->selectedWidgetId = mdiWindow->winId();
			if ( this->selectedWidgetId == 0 ) {
				QMessageBox::warning(this, tr("ScreenShot Warning"), tr("Failed selecting widget. Widget ID is invalid!") );
			 }
			QString name = mdiWindow->objectName();
			IReflection* irWin = dynamic_cast<IReflection*>(mdiWindow->widget());
			if ( irWin != NULL )
				name = QString( irWin->getClassName() );
			this->originalPixmap = QPixmap::grabWidget(mdiWindow);
			this->m_ui->lblScreenShotDescription->setText(tr("Screenshot of Active Widget '%1' [%2]").arg(name).arg((qint64)this->selectedWidgetId));
			this->m_ui->txtFileName->setText( name.replace("::",".").replace("wosh", "WOSH").replace("gui", "GUI") + ".%1.");
		 }
	 }
	else {
		QMessageBox::critical(this, tr("Failed taking screenshot"), tr("Unknown option!") );
	 }

	updatePreview();
	this->m_ui->btnTakeShot->setEnabled(true);
	if ( this->m_ui->chkAutoHideMe->isChecked() )
		show();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void FormScreenshoter::btnTakeShot_clicked() {
	if ( this->m_ui->chkAutoHideMe->isChecked() )
		hide();
	this->m_ui->btnTakeShot->setDisabled(true);
	// always asynch:
	QTimer::singleShot(this->m_ui->spinShotDelay->value() * 1000, this, SLOT(shootScreen()));
 }

void FormScreenshoter::btnSave_clicked() {
	QString format = "png";
	QString initialPath = this->m_ui->txtOutputFolder->text() + getCurrentFileName() + format;
	if ( !initialPath.isEmpty() )
		this->originalPixmap.save(initialPath, format.toAscii());
 }

void FormScreenshoter::btnSaveTo_clicked() {
	QString format = "png";

	QString initialPath = this->quickSaveLastPath + getCurrentFileName() + format;
	QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), initialPath, 
													tr("%1 Files (*.%2);;All Files (*)").arg(format.toUpper()).arg(format));
	if ( fileName.isEmpty() )
		return;
	this->originalPixmap.save(fileName, format.toAscii());
	this->quickSaveLastPath = QDir(fileName).absolutePath();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace application
}; // namespace wosh
